package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggestOption;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumListStartVo;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.Asserts;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private CategoryFeignClient categoryFeignClient;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private AlbumIndexRepository albumIndexRepository;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private ElasticsearchClient elasticsearchClient;
    @Autowired
    private SuggestIndexRepository suggestIndexRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 上架专辑
     *
     * @param albumId
     */
    @Override
    public void upperAlbum(Long albumId) {
        //汇总到索引库对象AlbumInfoIndex
        //albumInfoData
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();


        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //根据albumId获取albumInfo 专辑基本信息
            Result<AlbumInfo> albumInfo = albumInfoFeignClient.getAlbumInfo(albumId);
            Asserts.notNull(albumInfo, "专辑列表不存在");
            AlbumInfo albumInfoData = albumInfo.getData();
            Asserts.notNull(albumInfoData, "专辑不存在");
            BeanUtils.copyProperties(albumInfoData, albumInfoIndex);
            return albumInfoData;
        }, threadPoolExecutor);


        CompletableFuture<Void> albumAttributeValueCompletableFuture = CompletableFuture.runAsync(() -> {
            //  获取属性标签
            Result<List<AlbumAttributeValue>> albumAttributeValue1 = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Asserts.notNull(albumAttributeValue1, "专辑属性值列表不存在");
            List<AlbumAttributeValue> albumAttributeValueData = albumAttributeValue1.getData();
            Asserts.notNull(albumAttributeValueData, "专辑属性值不存在");

            //List<AlbumAttributeValue> albumAttributeValueData
            if (!CollectionUtils.isEmpty(albumAttributeValueData)) {
                List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueData.stream().map(albumAttributeValue -> {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                    return attributeValueIndex;
                }).collect(Collectors.toList());
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
        }, threadPoolExecutor);

        CompletableFuture<Void> baseCategoryViewCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync((albumInfoData) -> {
            //根据三级分类id获取三级分类属性 专辑分类信息 --专辑微服务提供数据
            Result<BaseCategoryView> categoryView = categoryFeignClient.getCategoryView(albumInfoData.getCategory3Id());
            Asserts.notNull(categoryView, "专辑分类列表不存在");
            BaseCategoryView baseCategoryViewData = categoryView.getData();
            Asserts.notNull(baseCategoryViewData, "分类不存在");
            //baseCategoryViewData
            albumInfoIndex.setCategory1Id(baseCategoryViewData.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryViewData.getCategory2Id());
            albumInfoIndex.setCategory3Id(baseCategoryViewData.getCategory3Id());
        }, threadPoolExecutor);


        CompletableFuture<Void> userInfoCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync((albumInfoData) -> {
            //根据用户id获取用户信息 用户信息
            Result<UserInfoVo> userInfoVo = userInfoFeignClient.getUserInfoVo(albumInfoData.getUserId());
            Asserts.notNull(userInfoVo, "用户列表不存在");
            UserInfoVo userInfoVoData = userInfoVo.getData();
            Asserts.notNull(userInfoVoData, "用户不存在");
            //userInfoVoData
            albumInfoIndex.setAnnouncerName(userInfoVoData.getNickname());
        }, threadPoolExecutor);


        CompletableFuture<Void> albumStartCompletableFuture = CompletableFuture.runAsync(() -> {
            //根据albumId获取专辑统计信息
            Result<AlbumListStartVo> albumStartValue = albumInfoFeignClient.findAlbumStartValue(albumId);
            Asserts.notNull(albumStartValue, "专辑统计列表不存在");
            AlbumListStartVo albumStartValueData = albumStartValue.getData();
            Asserts.notNull(albumStartValueData, "专辑统计不存在");

            //albumStartValueData
            Integer playStatNum = albumStartValueData.getPlayStatNum(); //播放量
            Integer subscribeStatNum = albumStartValueData.getSubscribeStatNum();//订阅量
            Integer buyStatNum = albumStartValueData.getBuyStatNum();//购买量
            Integer commentStatNum = albumStartValueData.getCommentStatNum();//评论数

            albumInfoIndex.setPlayStatNum(playStatNum);
            albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
            albumInfoIndex.setBuyStatNum(buyStatNum);
            albumInfoIndex.setCommentStatNum(commentStatNum);
            //  设置热度排名
            double hotScore = playStatNum * 0.2 + subscribeStatNum * 0.3 + buyStatNum * 0.4 + commentStatNum * 0.1;
            albumInfoIndex.setHotScore(hotScore);
        }, threadPoolExecutor);
        //  进行多任务组合：
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                albumAttributeValueCompletableFuture,
                baseCategoryViewCompletableFuture,
                userInfoCompletableFuture,
                albumStartCompletableFuture
        ).join();

        //  保存商品上架信息
        albumIndexRepository.save(albumInfoIndex);

        //  上架添加提词数据.
        //  创建对象 专辑标题提词
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replace("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        this.suggestIndexRepository.save(suggestIndex);
        //  专辑简介提词
        SuggestIndex albumIntroSuggestIndex = new SuggestIndex();
        albumIntroSuggestIndex.setId(UUID.randomUUID().toString().replace("-", ""));
        albumIntroSuggestIndex.setTitle(albumInfoIndex.getAlbumIntro());
        albumIntroSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        albumIntroSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        albumIntroSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        this.suggestIndexRepository.save(albumIntroSuggestIndex);
        // 专辑主播提词
        SuggestIndex announcerSuggestIndex = new SuggestIndex();
        announcerSuggestIndex.setId(UUID.randomUUID().toString().replace("-", ""));
        announcerSuggestIndex.setTitle(albumInfoIndex.getAnnouncerName());
        announcerSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAnnouncerName()}));
        announcerSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAnnouncerName())}));
        announcerSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAnnouncerName())}));
        this.suggestIndexRepository.save(announcerSuggestIndex);

        //	将新增的商品SKUID存入布隆过滤器
        //	获取布隆过滤器客户端
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        //通过 布隆过滤器客户端 将新增skuID存入布隆过滤器
        bloomFilter.add(albumInfoIndex.getId());
    }

    /**
     * 下架专辑
     *
     * @param albumId
     */
    @Override
    public void lowerAlbum(Long albumId) {
        albumIndexRepository.deleteById(albumId);
    }

    /**
     * 搜索Es专辑
     *
     * @param albumIndexQuery
     * @return
     */
    @SneakyThrows
    @Override
    public AlbumSearchResponseVo searchAlbum(AlbumIndexQuery albumIndexQuery) {
        //调用buildDsl方法动态生成dsl 返回SearchRequest
        SearchRequest request = this.buildDsl(albumIndexQuery);
        //通过Es客户端elasticsearchClient查询
        SearchResponse<AlbumInfoIndex> search = elasticsearchClient.search(request, AlbumInfoIndex.class);
        //处理Es客户端返回的结果集到AlbumSearchResponseVo
        AlbumSearchResponseVo albumSearchResponseVo = this.parseSearchVo(search);
        //赋值AlbumSearchResponseVo内的分页字段
        albumSearchResponseVo.setTotal(search.hits().total().value());//总页数 从es查询结果中获取
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize()); //页数 从前端参数中获取
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());//页大小 从前端参数中获取
        //通过 页数算法 计算总页数
        long totalPages = (albumSearchResponseVo.getTotal() + albumIndexQuery.getPageSize() - 1) / albumIndexQuery.getPageSize();
        albumSearchResponseVo.setTotal(totalPages);//总页数 通过算法计算

        return albumSearchResponseVo;
    }

    /**
     * 处理Es客户端返回的结果集到AlbumSearchResponseVo
     *
     * @param search
     * @return
     */
    private AlbumSearchResponseVo parseSearchVo(SearchResponse<AlbumInfoIndex> search) {
        //  主要给 private List<AlbumInfoIndexVo> list = new ArrayList<>(); 属性赋值;
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //  获取数据
        List<Hit<AlbumInfoIndex>> hits = search.hits().hits();
        //非空判断
        if (!CollectionUtils.isEmpty(hits)) {

            List<AlbumInfoIndexVo> albumInfoIndexVos = hits.stream().map(hit -> {
                //创建 list 类型对象
                AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
                AlbumInfoIndex source = hit.source();
                BeanUtils.copyProperties(source, albumInfoIndexVo);
                //  判断用户是否根据关键词进行检索.
                if (null != hit.highlight().get("albumTitle")) {
                    //  获取高亮数据
                    String albumTitle = hit.highlight().get("albumTitle").get(0);
                    //  赋值高亮数据
                    albumInfoIndexVo.setAlbumTitle(albumTitle);
                }
                //  返回数据
                return albumInfoIndexVo;
            }).collect(Collectors.toList());
            //  赋值
            albumSearchResponseVo.setList(albumInfoIndexVos);
        }
        //  返回数据
        return albumSearchResponseVo;
    }

    /**
     * 构建dsl
     *
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest buildDsl(AlbumIndexQuery albumIndexQuery) {
        //创建返回的 SearchRequest
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        //创建 searchRequestBuilder 需要的 BoolQuery {query - bool }
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
        //1.  判断用户是否根据关键词检索
        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())) {
            //添加dql语句逻辑
            boolQueryBuilder.should(f -> f.match(s -> s.field("albumTitle").query(albumIndexQuery.getKeyword())))
                    .should(f -> f.match(s -> s.field("albumIntro").query(albumIndexQuery.getKeyword())))
                    .should(f -> f.match(s -> s.field("announcerName").query(albumIndexQuery.getKeyword())));
            //添加dql语句 高亮
            searchRequestBuilder.highlight(f -> f.fields("albumTitle", s -> s.preTags("<span style=color:red>").postTags("</span>")));

        }
        //  2.  判断当前用户是否根据分类Id
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
            //添加dql语句逻辑
            boolQueryBuilder.filter(f -> f.term(s -> s.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
            boolQueryBuilder.filter(f -> f.term(s -> s.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
            boolQueryBuilder.filter(f -> f.term(s -> s.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }
        //  3. 根据属性值进行过滤 属性id:属性值id
        List<String> attributeList = albumIndexQuery.getAttributeList();
        //  判断集合是否为空
        if (!CollectionUtils.isEmpty(attributeList)) {
            //  循环遍历
            for (String attribute : attributeList) {
                //  attribute=属性id:属性值id 分割字符串
                String[] split = attribute.split(":");
                //添加 nested 模式 dql的逻辑
                if (null != split && split.length == 2) {
                    boolQueryBuilder.filter(t -> t.nested(q -> q.path("attributeValueIndexList").query(m -> m.bool(n -> (n.filter(o -> o.term(i -> i.field("attributeValueIndexList.attributeId").value(split[0])))
                            .filter(y -> y.term(r -> r.field("attributeValueIndexList.valueId").value(split[1])))
                    )))));
                }
            }
        }
        //  在searchRequestBuilder上添加分页属性
        Integer from = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchRequestBuilder.from(from);
        searchRequestBuilder.size(albumIndexQuery.getPageSize());
        // 在searchRequestBuilder 上设置排序属性 排序规则 综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序
        String order = albumIndexQuery.getOrder();
        if (!StringUtils.isEmpty(order)) {
            String[] split = order.split(":");
            if (null != split && split.length == 2) {
                //  声明一个排序字段
                String finalField = "";
                //  判断根据哪个字段进行排序
                switch (split[0]) {
                    case "1":
                        finalField = "hotScore"; //综合排序
                        break;
                    case "2":
                        finalField = "playStatNum"; //播放量
                        break;
                    case "3":
                        finalField = "createTime"; //发布时间
                        break;
                }
                //  设置排序规则
                String finalField1 = finalField;
                searchRequestBuilder.sort(t -> t.field(s -> s.field(finalField1).order("asc".equals(finalField1) ? SortOrder.Asc : SortOrder.Desc)));
            }
        }
        searchRequestBuilder.index("albuminfo").query(f -> f.bool(boolQueryBuilder.build()));
        SearchRequest build = searchRequestBuilder.build();
        //打印sql
        System.out.println("build:\t = " + build);
        return build;
    }


    /**
     * 获取频道页数据
     *
     * @param categoryId
     * @return
     */
    @SneakyThrows
    @Override
    public List<Map<String, Object>> channel(Long categoryId) {
        //  根据一级分类Id 获取到置顶数据集合
        Result<List<BaseCategory3>> channelList = categoryFeignClient.findChannel(categoryId);
        Asserts.notNull(channelList, "频道列表不存在");
        //  获取数据
        List<BaseCategory3> channelListData = channelList.getData();
        Asserts.notNull(channelListData, "频道列表不存在");

        //  将baseCategory3List 这个集合转换为map 集合 key=category3Id value = category3;
        //Map<Long, BaseCategory3> baseCategory3Map = channelListData.stream().collect(Collectors.toMap(baseCategory3 ->  baseCategory3.getId(), baseCategory3 -> baseCategory3));
        Map<Long, BaseCategory3> baseCategory3Map = channelListData.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        //  获取到三级分类Id 集合
        List<Long> category3List = channelListData.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //转换为dsl语句中需要的FieldValue格式
        List<FieldValue> fieldValues = category3List.stream().map(category3 -> FieldValue.of(category3)).collect(Collectors.toList());
        //合二为一
        // List<FieldValue> fieldValues2 = channelListData.stream().map(channeData -> FieldValue.of(channeData.getId())).collect(Collectors.toList());/

        //  编写dsl语句;
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                        .query(t -> t.terms(f -> f.field("category3Id")
                                .terms(f1 -> f1.value(fieldValues))))
                        .aggregations("groupByCategory3IdAgg", a -> a.terms(t -> t.field("category3Id").size(10))
                                .aggregations("topTenHotScoreAgg", t -> t.topHits(s1 -> s1.size(6).sort(s2 -> s2.field(s3 -> s3.field("hotScore").order(SortOrder.Desc)))))
                        )
                , AlbumInfoIndex.class);

        //获取Es 查询结果集中的数据
        Aggregate groupByCategory3IdAgg = searchResponse.aggregations().get("groupByCategory3IdAgg");
        //循环比例结果集 数组
        List<Map<String, Object>> collectMap = groupByCategory3IdAgg.lterms().buckets().array().stream().map(groupByCategory3Id -> {
            //  获取三级分类Id 对象
            long groupByCategory3Key = groupByCategory3Id.key();
            //  获取要置顶的集合数据
            Aggregate topTenHotScoreAgg = groupByCategory3Id.aggregations().get("topTenHotScoreAgg");
            //  循环遍历获取聚合中的数据
            List<AlbumInfoIndex> infoIndexList = topTenHotScoreAgg.topHits().hits().hits().stream().map(topTenHot -> {
                //  获取到source 的json 字符串数据
                String source = topTenHot.source().toString();
                //  将json 字符串转换为AlbumInfoIndex 对象
                AlbumInfoIndex albumInfoIndex = JSON.parseObject(source, AlbumInfoIndex.class);
                //返回 聚合中单个 AlbumInfoIndex
                return albumInfoIndex;

            }).collect(Collectors.toList());  //将所有AlbumInfoIndex 整合为list
            //  声明一个map 集合数据
            Map<String, Object> map = new HashMap<>();
            //  存储 根据三级分类Id 要找到的三级分类
            map.put("baseCategory3", baseCategory3Map.get(groupByCategory3Key));
            //  存储所有的专辑集合将所有AlbumInfoIndex数据
            map.put("list", infoIndexList);
            //返回map
            return map;

        }).collect(Collectors.toList());  //将返回的map 整合为list

        //返回map结果
        return collectMap;
    }

    /**
     * 自动补全
     *
     * @param keyword
     * @return
     */
    @SneakyThrows
    @Override
    public List<String> completeSuggest(String keyword) {

        SearchResponse<SuggestIndex> search = elasticsearchClient.search(s -> s.index("suggestinfo").suggest(
                s1 -> s1.suggesters("suggestionKeyword", f -> f.prefix(keyword).completion(f1 -> f1.field("keyword")
                                .skipDuplicates(true).size(10).fuzzy(f2 -> f2.fuzziness("auto"))))
                        .suggesters("suggestionkeywordPinyin", f3 -> f3.prefix(keyword).completion(f4 -> f4.field("keywordPinyin")
                                .skipDuplicates(true).size(10).fuzzy(f5 -> f5.fuzziness("auto"))))
                        .suggesters("suggestionkeywordSequence", f6 -> f6.prefix(keyword).completion(f7 -> f7.field("keywordSequence")
                                .skipDuplicates(true).size(10).fuzzy(f8 -> f8.fuzziness("auto"))))
        ), SuggestIndex.class);


        List<String> arrayList = new ArrayList<>();
        arrayList.addAll(this.parseResultDate(search, "suggestionKeyword"));
        arrayList.addAll(this.parseResultDate(search, "suggestionkeywordPinyin"));
        arrayList.addAll(this.parseResultDate(search, "suggestionkeywordSequence"));


        return arrayList;
    }


    /**
     * 转换结果集
     *
     * @param search
     * @param keyword
     * @return
     */
    private Collection<String> parseResultDate(SearchResponse<SuggestIndex> search, String keyword) {
        List<Suggestion<SuggestIndex>> suggestions = search.suggest().get(keyword);

        for (Suggestion<SuggestIndex> suggestion : suggestions) {

            List<String> titleList = suggestion.completion().options().stream().map(suggestion1 -> {
                return suggestion1.source().getTitle();
            }).collect(Collectors.toList());
            return titleList;
        }
        return null;
    }

    /**
     * 更新排行榜
     */
    @SneakyThrows
    @Override
    public void updateLatelyAlbumRanking() {
        //  1.  远程调用接口获取到所有的一级分类Id列表;
        Result<List<BaseCategory1>> channel1List = categoryFeignClient.findAllChannel1();
        Asserts.notNull(channel1List, "一级分类结果集为空");
        List<BaseCategory1> channel1Data = channel1List.getData();
        Asserts.notNull(channel1Data, "一级分类结果集为空");
        //  2.循环遍历
        for (BaseCategory1 channel1Datum : channel1Data) {
            //  定义 五个维度 数组
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            //循环遍历五个维度
            for (String rankingDimension : rankingDimensionArray) {
                //  定义Dsl语句
                SearchResponse<AlbumInfoIndex> search = elasticsearchClient.search(s -> s.index("albuminfo")
                                .query(t -> t.term(f1 -> f1.field("category1Id").value(channel1Datum.getId())))
                                .sort(f2 -> f2.field(f3 -> f3.field(rankingDimension).order(SortOrder.Desc)))
                                .size(10)
                        , AlbumInfoIndex.class);
                //  获取 Hash数据: .hits().hits() _source
                List<AlbumInfoIndex> searchInfoList = search.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //  放入缓存;hset key field value;
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+channel1Datum.getId(),rankingDimension,searchInfoList);


            }
        }
    }

    /**
     * 获取排行榜
     * @param trackId
     * @param dimension
     * @return
     */
    @Override
    public List<AlbumInfoIndexVo> findRankingList(Long trackId, String dimension) {

        return (List<AlbumInfoIndexVo>) redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX+trackId,dimension);
    }
}
